package com.client;

import com.client.entity.B_client;
import com.client.entity.PassAuthor;
import com.client.entity.sm9.Key;
import com.client.mapper.PassAuthorDao;
import com.client.service.Certification;
import com.client.service.KeyService;
import com.client.service.MessageService;
import com.client.sm9.gm.sm9.SM9Utils;
import com.client.utils.MessageHandler;
import com.client.utils.MessageUtils;
import com.client.utils.UDPUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.io.FileNotFoundException;
import java.util.UUID;

import static java.lang.Thread.sleep;

@Slf4j
@Component
@EnableAsync
//初始化操作
public class Initialize implements ApplicationRunner {
    //是否可以进行计算迁移
    public static boolean HPS = false;

    @Autowired
    KeyService keyService;
    @Autowired
    PassAuthorDao passAuthorDao;
    @Autowired
    Certification certification;
    @Autowired
    UDPUtil udp;
    @Autowired
    MessageService messageService;
    @Autowired
    MessageHandler messageHandler;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        //数据库是否建立，执行sql文件

        //开始消息重发服务
        messageHandler.messageResendHandler();
        //删除认证超时的对象
        messageHandler.CertificationMessageResendHandler();

        //检查是否有公私钥，没有的话向KGC发起请求
        checkPrivateKey();
//        //检查与高性能服务器是否有AES密钥，没有的话先进行认证流程获取密钥
//        checkAESkey();
//        //登录设备管理平台
        login();
        //以上都通过的话则启动成功，可正常工作
    }

    //检查是否有公私钥，没有的话向KGC发起请求
    public void checkPrivateKey() {
        log.info("终端标识为：" + keyService.getId());
        while (true) {
            if (keyService.getPpub_e() != null &&
                    keyService.getPpub_s() != null &&
                    keyService.getDe() != null &&
                    keyService.getDs() != null &&
                    keyService.getD_exchange() != null) {
                break;
            } else {
                log.info("密钥不完整，将向KGC请求密钥");
                //向KGC平台请求私钥并保存
                Key key = keyService.getKeyFormKGC(keyService.getId());
                try {
                    keyService.saveKey(key);
                    log.info("将向KGC请求密钥成功");
                } catch (FileNotFoundException e) {
                    log.info("密钥保存失败");
                }
            }
        }
        log.info("加密主公钥为：" + keyService.getPpub_e());
        log.info("签名主公钥为：" + keyService.getPpub_s());
        log.info("加密私钥为：" + keyService.getDe());
        log.info("签名私钥为：" + keyService.getDs());
        log.info("密钥交换密钥为：" + keyService.getD_exchange());
        log.info("密钥完整");

    }

    //检查与高性能服务器是否有AES密钥，没有的话先进行认证流程获取密钥
    public void checkAESkey() {
        //高性能服务器--HPS
        PassAuthor hps = passAuthorDao.queryByName("HPS");
        while (true) {
            if (hps != null && hps.getK() != null) {
                HPS = true;
                break;
            } else {
                log.info("与计算迁移平台的AES密钥不存在，将开始与HPS的认证");

            }
        }
        log.info("与计算迁移平台的AES密钥为：" + SM9Utils.toHexPureString(hps.getK()));
        log.info("可进行计算迁移");
    }


    public void login() {
        byte[] bytes = new byte[0];
        UUID uid = MessageUtils.getuuid();
        try {
            bytes = certification.send1("Certification", uid);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //尝试登陆设备管理平台
        messageService.newClient(uid, "Certification", 8855, "127.0.0.1");
        messageService.getClient("Certification").setTime(MessageUtils.getNowTime());
        udp.send("127.0.0.1", 8855, bytes);

        while (true) {
            try {
                sleep(1000); //休眠100毫秒
                B_client certification = messageService.getClient("Certification");

                if (certification != null && certification.getExchang_flag() == -2) {
                    log.info("登录设备管理平台成功！");
                    return;
                } else if (certification == null || certification.getExchang_flag() == -1) {
                    log.info("登录设备管理平台失败！");
                    return;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
